/**
 * @file      : miscellaneous.h
 * @brief     : 杂项函数集合头文件
 * @author    : huenrong (huenrong1028@gmail.com)
 * @date      : 2020-08-20 17:51:15
 *
 * @copyright : Copyright (c) 2020  成都科鸿凌泰自动识别技术有限公司
 *
 */

#ifndef __MISCELLANEOUS_H
#define __MISCELLANEOUS_H

#include <stdint.h>

// 定义日期结构
struct date_time
{
    uint16_t year;  // 4位年份值, 例: 1995
    uint8_t month;  // [1-12]
    uint8_t day;    // [1-31]
    uint8_t hour;   // [0-23]
    uint8_t minute; // [0-59]
    uint8_t second; // [0-60]
};

/**
 * @brief  获取编译时间戳
 * @param  get_timer: 输出参数: 获取到的时间戳
 */
void get_compile_time(char *get_timer);

/**
 * @brief  获取系统当前时区
 * @return 当前系统时区
 */
int get_local_time_zone(void);

/**
 * @brief  获取系统当前时间字符串(精确到毫秒)
 * @param  time_buf: 输出参数, 获取到的时间串
 * @param  gap_flag: 输入参数, 获取到的时间是否需要间隔
 *                            0: 无间隔: 20180806163000616678
 *                            1: 有间隔: 2018-08-06 16:30:00.616678
 *                            2: 有间隔: 2018-08-06_16-30-00-616678
 */
void get_time_str(char *time_buf, const uint8_t gap_flag);

/**
 * @brief  获取系统当前时间
 * @param  local_time: 输出参数, 获取到的本地时间
 */
void get_local_time(struct date_time *local_time);

/**
 * @brief  设置系统当前时间
 * @param  year: 输入参数, 待设置年, 4位年份值, 例: 1995
 * @param  mon : 输入参数, 待设置月, 取值范围: [1, 12]
 * @param  mday: 输入参数, 待设置日, 取值范围: [1, 31]
 * @param  hour: 输入参数, 待设置时, 取值范围: [0, 23]
 * @param  min : 输入参数, 待设置分, 取值范围: [0, 59]
 * @param  sec : 输入参数, 待设置秒, 取值范围: [0, 60]
 * @return 成功: 0
 *         失败: errno错误码
 */
int set_local_time(const uint16_t year, const uint8_t mon, const uint8_t mday,
                   const uint8_t hour, const uint8_t min, const uint8_t sec);

/**
 * @brief  获取本地ip地址
 * @param  ip_str: 输出参数, 获取到的ip地址
 * @param  ifname: 输入参数, 网卡名字(如: eth0, eth1...)
 * @return 成功: 0
 *         失败: -1
 */
int get_local_ip(char *ip_str, const char *ifname);

/**
 * @brief  设置本地ip地址
 * @param  ip_str: 输入参数, 待设置ip地址
 * @param  ifname: 输入参数, 待设置网卡名字(如: eth0, eth1...)
 * @return 成功: 0
 *         失败: -1
 */
int set_local_ip(const char *ip_str, const char *ifname);

/**
 * @brief  获取本地子网掩码
 * @param  netmask_str: 输出参数, 获取到的子网掩码
 * @param  ifname  : 输入参数, 网卡名字(如: eth0, eth1...)
 * @return 成功: 0
 *         失败: -1
 */
int get_local_netmask(char *netmask_str, const char *ifname);

/**
 * @brief  设置本地子网掩码
 * @param  netmask_str: 输入参数, 待设置子网掩码
 * @param  ifname  : 输入参数, 待设置网卡名字(如: eth0, eth1...)
 * @return 成功: 0
 *         失败: -1
 */
int set_local_netmask(const char *netmask_str, const char *ifname);

/**
 * @brief  获取本机默认网关
 * @param  gateway_addr_str: 输出参数, 获取到的默认网关
 * @return 成功: 0
 *         失败: -1
 */
int get_local_gateway_addr(char *gateway_addr_str);

/**
 * @brief  设置本机默认网关
 * @param  gateway_addr_str: 输入参数, 待设置的默认网关
 * @return 成功: 0
 *         失败: -1
 */
int set_local_gateway_addr(const char *gateway_addr_str);

/**
 * @brief  把16进制转换为ASCII字符
 * @param  hex: 输入参数, 需要转换的16进制
 * @return 转换后的ASCII字符
 */
uint8_t hex_to_ascii(const uint8_t hex);

/**
 * @brief  ASCII码转hex字符(0~9, A~F的ASCII码还原成0~15)
 * @param  ascii: 输入参数, 需要转换的ASCII字符
 * @return 转换完成的hex字符
 */
uint8_t ascii_to_hex(const uint8_t ascii);

/**
 * @brief  十六进制字符转换成普通字符
 * @param  str    : 输出参数, 转换后的字符
 * @param  hex    : 输入参数, 要转换的字符
 * @param  hex_len: 输入参数, 要转换的字符长度
 * @return 转换后的字符长度
 */
uint32_t hex_to_str(uint8_t *str, const uint8_t *hex, const uint32_t hex_len);

/**
 * @brief  十六进制字符串转换为字节流
 * @param  dest      : 输出参数, 转换后的字节流
 * @param  source    : 输入参数, 要转换的字符串
 * @param  source_len: 输入参数, 需要转换的字符串的长度
 */
void hex_str_to_byte(uint8_t *dest, const char *source, const int source_len);

/**
 * @brief  根据unix时间戳计算本地时间
 * @param  local_time: 输出参数, 获取到的本地时间
 * @param  unix_time : 输入参数, unix时间戳
 */
void unix_time_to_local_time(struct date_time *local_time,
                             const uint64_t unix_time);

/**
 * @brief  根据本地时间计算unix时间戳
 * @param  unix_time : 输出参数, 获取到的unix时间戳
 * @param  local_time: 输入参数, 本地时间
 */
void local_time_to_unix_time(uint32_t *unix_time,
                             const struct date_time local_time);

/**
 * @brief  目标数据查找
 * @param  source_data         : 输入参数, 源数据
 * @param  source_data_len     : 输入参数, 源数据长度
 * @param  destination_data    : 输入参数, 目标数据
 * @param  destination_data_len: 输入参数, 目标数据长度
 * @return 成功: 返回目标字符串第一个字符的位置
 *         失败: 返回-1
 */
int destination_data_lookup(const uint8_t *source_data,
                            const uint16_t source_data_len,
                            const uint8_t *destination_data,
                            const uint8_t destination_data_len);

/**
 * @brief  大小端交换
 * @param  source_data: 输入参数, 源数据
 * @return 交换后的数据
 */
uint32_t byte_swap_32(const uint32_t source_data);

/**
 * @brief  执行命令并获取输出结果
 * @param  result: 输出参数, 命令输出结果
 * @param  cmd   : 输入参数, 待执行命令
 * @return 成功: 返回0
 *         失败: 返回-1
 */
int execute_cmd(char *result, const char *cmd);

/**
 * @brief  清空socket缓存区
 * @param  fd: 输入参数, 文件描述符
 * @return 成功: 0
 *         失败: -1
 */
int clear_socket_cache(const int fd);

/**
 * @brief  获取文件大小
 * @param  file_path: 输入参数, 文件路径
 * @return 成功: 返回文件大小(单位: bytes)
 *         失败: -1
 */
long int get_file_size(const char *file_path);

/**
 * @brief  计算文件md5校验
 * @param  file_md5 : 输出参数, 获取到的文件md5校验
 * @param  file_path: 输入参数, 文件路径
 * @return 成功: 0
 *         失败: -1
 */
int get_file_md5(char *file_md5, const char *file_path);

#endif /* __MISCELLANEOUS_H */
